package cn.schoolwow.sdk.weiyun;

import cn.schoolwow.quickhttp.QuickHttp;
import cn.schoolwow.quickhttp.client.CookieOption;
import cn.schoolwow.quickhttp.domain.RequestMeta;
import cn.schoolwow.quickhttp.listener.QuickHttpClientListener;
import cn.schoolwow.quickhttp.request.Request;
import cn.schoolwow.quickhttp.response.Response;
import cn.schoolwow.sdk.weiyun.domain.*;
import cn.schoolwow.sdk.weiyun.exception.WeiYunException;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.HttpCookie;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import java.util.function.Consumer;

/**
 * 微云SDK实现类
 */
public class WeiYunAPIImpl implements WeiYunAPI {
    private Logger logger = LoggerFactory.getLogger(WeiYunAPI.class);
    private String skey;
    private String gtk;
    /**根目录*/
    private volatile WeiYunDirectory rootDirectory;

    public WeiYunAPIImpl(String cookieString) {
        setCookie(cookieString);
    }

    @Override
    public void setCookie(String cookieString) {
        CookieOption cookieOption = QuickHttp.clientConfig().cookieOption();
        cookieOption.addCookieString("weiyun.com", cookieString);
        HttpCookie skeyCookie = cookieOption.getCookie("weiyun.com", "skey");
        if (null != skeyCookie) {
            skey = skeyCookie.getValue();
        }else{
            QuickHttp.clientConfig().cookieOption().addCookie("share.weiyun.com", "wyctoken", "854045919");
        }
        HttpCookie gtkCookie = cookieOption.getCookie("weiyun.com", "wyctoken");
        if (null != gtkCookie) {
            gtk = gtkCookie.getValue();
        }
        if(cookieOption.hasCookie("weiyun.com","FTN5K")){
            cookieOption.removeCookie("weiyun.com","FTN5K");
        }
        QuickHttp.clientConfig().quickHttpClientListener(new QuickHttpClientListener() {
            @Override
            public void beforeExecute(Request request) throws IOException{
                RequestMeta requestMeta = request.requestMeta();
                if(requestMeta.url.getHost().contains("weiyun.com")){
                    request.method(Request.Method.POST)
                            .ignoreHttpErrors(true);
                    if(null==requestMeta.contentType){
                        request.contentType(Request.ContentType.APPLICATION_JSON);
                    }
                }
            }

            @Override
            public void executeSuccess(Request request, Response response) throws IOException{
                JSONObject result = response.bodyAsJSONObject();
                if (null!=result && result.containsKey("ret") && 0 != result.getInteger("ret")) {
                    throw new WeiYunException(result.getInteger("ret"), result.getString("msg"));
                }
                JSONObject rspHeader= null;
                if(result.containsKey("rsp_header")){
                    rspHeader = result.getJSONObject("rsp_header");
                }else if(result.containsKey("data")&&result.getJSONObject("data").containsKey("rsp_header")){
                    rspHeader = result.getJSONObject("data").getJSONObject("rsp_header");
                }
                if (0 == rspHeader.getInteger("retcode")) {
                    return;
                }
                throw new WeiYunException(rspHeader.getInteger("retcode"), rspHeader.getString("retmsg"));
            }

            @Override
            public void executeFail(Request request, Exception e) throws IOException{

            }
        });
        try {
            diskUserInfoGet();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public boolean hasCookieExpire() throws IOException {
        String api = "https://www.weiyun.com/webapp/json/weiyunQdiskClient/DiskUserInfoGet?refer=chrome_windows&g_tk=" + gtk + "&r=" + Math.random();
        String body = getBody(2201, "\\\".weiyun.DiskUserInfoGetMsgReq_body\\\":{\\\"is_get_upload_flow_flag\\\":true,\\\"is_get_high_speed_flow_info\\\":true,\\\"is_get_weiyun_flag\\\":true}");
        Response response = QuickHttp.newQuickHttpClient()
                .connect(api)
                .method(Request.Method.POST)
                .ignoreHttpErrors(true)
                .requestBody(body)
                .execute();
        if (response.statusCode() != 200 || response.body().contains("(190051)您的登录态已失效")) {
            return true;
        }
        return false;
    }

    @Override
    public UserConfig diskUserInfoGet() throws IOException {
        String api = "https://www.weiyun.com/webapp/json/weiyunQdiskClient/DiskUserInfoGet?refer=chrome_windows&g_tk=" + gtk + "&r=" + Math.random();
        String body = getBody(2201, "\\\".weiyun.DiskUserInfoGetMsgReq_body\\\":{\\\"is_get_upload_flow_flag\\\":true,\\\"is_get_high_speed_flow_info\\\":true,\\\"is_get_weiyun_flag\\\":true}");
        Response response = QuickHttp.connect(api)
                .requestBody(body)
                .execute();
        UserConfig userConfig = getResponse(response,UserConfig.class);

        rootDirectory = new WeiYunDirectory();
        rootDirectory.pdirKey = userConfig.rootDirKey;
        rootDirectory.dirKey = userConfig.mainDirKey;
        return userConfig;
    }

    @Override
    public WeiYunDirectory diskDirBatchList(WeiYunDirectory weiYunDirectory) throws IOException {
        if(null==weiYunDirectory){
            weiYunDirectory = rootDirectory;
        }
        String dirKey = weiYunDirectory.dirKey;
        String pdirKey = weiYunDirectory.pdirKey;
        String api = "https://www.weiyun.com/webapp/json/weiyunQdisk/DiskDirBatchList?refer=chrome_windows&g_tk=" + gtk + "&r=" + Math.random();
        String body = getBody(2209, "\\\".weiyun.DiskDirBatchListMsgReq_body\\\":{\\\"pdir_key\\\":\\\"" + pdirKey + "\\\",\\\"dir_list\\\":[{\\\"dir_key\\\":\\\"" + dirKey + "\\\",\\\"get_type\\\":0,\\\"start\\\":0,\\\"count\\\":100,\\\"sort_field\\\":2,\\\"reverse_order\\\":false,\\\"get_abstract_url\\\":true,\\\"get_dir_detail_info\\\":true}]}");
        Response response = QuickHttp.connect(api)
                .requestBody(body)
                .execute();
        JSONObject responseMessageBody = response.bodyAsJSONObject().getJSONObject("data").getJSONObject("rsp_body").getJSONObject("RspMsg_body");
        JSONObject result = responseMessageBody.getJSONArray("dir_list").getJSONObject(0);
        weiYunDirectory = new WeiYunDirectory();
        weiYunDirectory.pdirKey = result.getString("pdir_key");
        weiYunDirectory.weiYunFileList = getWeiYunFileList(result.getJSONArray("file_list"), dirKey, pdirKey);
        weiYunDirectory.weiYunDirectoryList = getWeiYunDirectoryList(result.getJSONArray("dir_list"), dirKey, pdirKey);
        return weiYunDirectory;
    }

    @Override
    public WeiYunDirectoryCreate diskDirCreate(WeiYunDirectory parentDirectory, String dirName) throws IOException {
        String api = "https://www.weiyun.com/webapp/json/weiyunQdiskClient/DiskDirCreate?refer=chrome_windows&g_tk=" + gtk + "&r=" + Math.random();
        String body = getBody(2614, "\\\".weiyun.DiskDirCreateMsgReq_body\\\":{\\\"pdir_key\\\":\\\"" + parentDirectory.pdirKey + "\\\",\\\"ppdir_key\\\":\\\"" + parentDirectory.ppdirKey + "\\\",\\\"dir_name\\\":\\\"" + dirName + "\\\",\\\"file_exist_option\\\":2,\\\"create_type\\\":1}");
        Response response = QuickHttp.connect(api)
                .requestBody(body)
                .execute();
        WeiYunDirectoryCreate weiYunDirectoryCreate = getResponse(response,WeiYunDirectoryCreate.class);
        return weiYunDirectoryCreate;
    }

    @Override
    public WeiYunDirectory diskDirFileBatchDeleteEx(List<WeiYunDirectory> weiYunDirectoryList, List<WeiYunFile> weiYunFileList) throws IOException {
        if (null == weiYunDirectoryList) {
            weiYunDirectoryList = new ArrayList<>();
        }
        if (null == weiYunFileList) {
            weiYunFileList = new ArrayList<>();
        }
        String api = "https://www.weiyun.com/webapp/json/weiyunQdiskClient/DiskDirFileBatchDeleteEx?refer=chrome_windows&g_tk=" + gtk + "&r=" + Math.random();
        StringBuilder bodyBuilder = new StringBuilder("\\\".weiyun.DiskDirFileBatchDeleteExMsgReq_body\\\":{\\\"file_list\\\":[");
        for (WeiYunFile weiYunFile : weiYunFileList) {
            bodyBuilder.append("{\\\"ppdir_key\\\":\\\"" + weiYunFile.ppdirKey + "\\\",\\\"pdir_key\\\":\\\"" + weiYunFile.pdirKey + "\\\",\\\"file_id\\\":\\\"" + weiYunFile.fileId + "\\\",\\\"filename\\\":\\\"" + weiYunFile.fileName + "\\\"},");
        }
        if (weiYunFileList.size() > 0) {
            bodyBuilder.deleteCharAt(bodyBuilder.length() - 1);
        }
        bodyBuilder.append("],\\\"dir_list\\\":[");
        for (WeiYunDirectory weiYunDirectory : weiYunDirectoryList) {
            bodyBuilder.append("{\\\"ppdir_key\\\":\\\"" + weiYunDirectory.ppdirKey + "\\\",\\\"pdir_key\\\":\\\"" + weiYunDirectory.pdirKey + "\\\",\\\"dir_key\\\":\\\"" + weiYunDirectory.dirKey + "\\\",\\\"dir_name\\\":\\\"" + weiYunDirectory.dirName + "\\\"},");
        }
        if (weiYunDirectoryList.size() > 0) {
            bodyBuilder.deleteCharAt(bodyBuilder.length() - 1);
        }
        bodyBuilder.append("]}");
        String body = getBody(2509, bodyBuilder.toString());
        Response response = QuickHttp.connect(api)
                .requestBody(body)
                .execute();
        JSONObject responseMessageBody = response.bodyAsJSONObject().getJSONObject("data").getJSONObject("rsp_body").getJSONObject("RspMsg_body");
        WeiYunDirectory weiYunDirectory = new WeiYunDirectory();
        weiYunDirectory.weiYunFileList = getWeiYunFileList(responseMessageBody.getJSONArray("file_list"), null, null);
        weiYunDirectory.weiYunDirectoryList = getWeiYunDirectoryList(responseMessageBody.getJSONArray("dir_list"), null, null);
        return weiYunDirectory;
    }

    @Override
    public WeiYunFile uploadFile(WeiYunDirectory weiYunDirectory, String filePath) throws IOException {
        if(null==weiYunDirectory){
            weiYunDirectory = rootDirectory;
        }
        Path path = Paths.get(filePath);
        if(Files.notExists(path)){
            throw new IllegalArgumentException("本地上传文件不存在!路径:"+filePath);
        }
        String api = "https://upload.weiyun.com/ftnup_v2/weiyun?cmd=247120";
        String body = "{\"req_header\":{\"cmd\":247120,\"appid\":30013,\"major_version\":3,\"minor_version\":0,\"fix_version\":0,\"version\":0,\"user_flag\":0},\"req_body\":{\"ReqMsg_body\":{\"weiyun.PreUploadMsgReq_body\":{\"common_upload_req\":{\"ppdir_key\":\""+weiYunDirectory.pdirKey+"\",\"pdir_key\":\""+weiYunDirectory.dirKey+"\",\"file_size\":"+Files.size(path)+",\"filename\":\""+path.getFileName().toString()+"\",\"file_exist_option\":6,\"use_mutil_channel\":true},\"upload_scr\":0,\"channel_count\":4}}}}";
        body = body.replace("\\\"","\"");
        Response response = QuickHttp.connect(api)
                .data("json",body)
                .data("upload",path)
                .contentType(Request.ContentType.MULTIPART_FORMDATA)
                .execute();
        JSONObject responseMessageBody = response.bodyAsJSONObject().getJSONObject("rsp_body").getJSONObject("RspMsg_body");
        WeiYunFile weiYunFile = responseMessageBody.getJSONObject("weiyun.PreUploadMsgRsp_body").getJSONObject("common_upload_rsp").toJavaObject(WeiYunFile.class);
        return weiYunFile;
    }

    @Override
    public WeiYunFileDownload diskFileBatchDownload(WeiYunFile weiYunFile) throws IOException {
        String api = "https://www.weiyun.com/webapp/json/weiyunQdiskClient/DiskFileBatchDownload?refer=chrome_windows&g_tk=" + gtk + "&r=" + Math.random();
        String body = getBody(2402, "\\\".weiyun.DiskFileBatchDownloadMsgReq_body\\\":{\\\"file_list\\\":[{\\\"file_id\\\":\\\"" + weiYunFile.fileId + "\\\",\\\"pdir_key\\\":\\\"" + weiYunFile.pdirKey + "\\\"}],\\\"download_type\\\":0}");
        Response response = QuickHttp.connect(api)
                .requestBody(body)
                .execute();
        JSONObject responseMessageBody = response.bodyAsJSONObject().getJSONObject("data").getJSONObject("rsp_body").getJSONObject("RspMsg_body");
        JSONObject result = responseMessageBody.getJSONArray("file_list").getJSONObject(0);
        WeiYunFileDownload weiYunFileDownload = getWeiYunFileDownload(result);
        return weiYunFileDownload;
    }

    @Override
    public WeiYunFileDownload diskFileBatchDownload(List<WeiYunDirectory> weiYunDirectoryList, List<WeiYunFile> weiYunFileList) throws IOException {
        if (null == weiYunDirectoryList && null == weiYunFileList) {
            throw new IllegalArgumentException("文件夹列表和文件列表参数不能同时为空!");
        }
        String zipName = generateFileName(weiYunDirectoryList, weiYunFileList);
        if (null == weiYunDirectoryList) {
            weiYunDirectoryList = new ArrayList<>();
        }
        if (null == weiYunFileList) {
            weiYunFileList = new ArrayList<>();
        }
        String api = "https://www.weiyun.com/webapp/json/weiyunQdiskClient/DiskFileBatchDownload?refer=chrome_windows&g_tk=" + gtk + "&r=" + Math.random();
        StringBuilder bodyBuilder = new StringBuilder("\\\".weiyun.DiskFilePackageDownloadMsgReq_body\\\":{\\\"pdir_list\\\":[{\\\"pdir_key\\\":\\\"" + weiYunFileList.get(0).pdirKey + "\\\",\\\"dir_list\\\":[");
        for (WeiYunDirectory weiYunDirectory : weiYunDirectoryList) {
            bodyBuilder.append("{\\\"dir_key\\\":\\\"" + weiYunDirectory.dirKey + "\\\",\\\"dir_name\\\":\\\"" + weiYunDirectory.dirName + "\\\"},");
        }
        if (weiYunDirectoryList.size() > 0) {
            bodyBuilder.deleteCharAt(bodyBuilder.length() - 1);
        }
        bodyBuilder.append("],\\\"file_list\\\":[");
        for (WeiYunFile weiYunFile : weiYunFileList) {
            bodyBuilder.append("{\\\"file_id\\\":\\\"" + weiYunFile.fileId + "\\\",\\\"pdir_key\\\":\\\"" + weiYunFile.pdirKey + "\\\"},");
        }
        if (weiYunFileList.size() > 0) {
            bodyBuilder.deleteCharAt(bodyBuilder.length() - 1);
        }
        bodyBuilder.append("],\\\"zip_filename\\\":\\\"" + zipName + "\\\"}");
        String body = getBody(2403, bodyBuilder.toString());
        Response response = QuickHttp.connect(api)
                .requestBody(body)
                .execute();
        WeiYunFileDownload weiYunFileDownload = getResponse(response,WeiYunFileDownload.class);
        weiYunFileDownload.dlink = QuickHttp.newQuickHttpClient()
                .connect(weiYunFileDownload.httpsDownloadUrl)
                .cookie(weiYunFileDownload.cookieName, weiYunFileDownload.cookieValue)
                .connectTimeout(10000);
        return weiYunFileDownload;
    }

    @Override
    public WeiYunShareView weiyunShareViewNoLogin(String url) throws IOException {
        return getWeiYunShareView(url,false);
    }

    @Override
    public WeiYunShareView weiyunShareView(String url) throws IOException {
        return getWeiYunShareView(url,true);
    }

    @Override
    public void weiyunShareDirList(WeiYunShareView weiYunShareView, WeiYunDirectory weiYunDirectory) throws IOException {
        String api = "https://share.weiyun.com/webapp/json/weiyunShare" + (skey == null ? "NoLogin" : "") + "/WeiyunShareDirList?refer=chrome_windows&g_tk=" + (gtk == null ? "854045919" : gtk) + "&r=" + Math.random();
        String body = getBody(12031, "\\\".weiyun.WeiyunShareDirListMsgReq_body\\\":{\\\"share_key\\\":\\\"" + weiYunShareView.shareKey + "\\\",\\\"share_pwd\\\":\\\"\\\",\\\"dir_key\\\":\\\"" + weiYunDirectory.dirKey + "\\\",\\\"dir_name\\\":\\\"" + weiYunDirectory.dirName + "\\\",\\\"get_type\\\":0,\\\"start\\\":0,\\\"count\\\":100,\\\"get_abstract_url\\\":true}");
        Response response = QuickHttp.connect(api)
                .requestBody(body)
                .execute();
        JSONObject responseMessageBody = response.bodyAsJSONObject().getJSONObject("data").getJSONObject("rsp_body").getJSONObject("RspMsg_body");
        weiYunDirectory.weiYunFileList = getWeiYunFileList(responseMessageBody.getJSONArray("file_list"), weiYunDirectory.pdirKey, weiYunDirectory.ppdirKey);
        weiYunDirectory.weiYunDirectoryList = getWeiYunDirectoryList(responseMessageBody.getJSONArray("dir_list"), weiYunDirectory.pdirKey, weiYunDirectory.ppdirKey);
    }

    @Override
    public void walkWeiYunShareViewWeiYunFile(WeiYunShareView weiYunShareView, Consumer<WeiYunFile> weiYunFileConsumer) throws IOException{
        for(WeiYunFile weiYunFile:weiYunShareView.weiYunFileList){
            weiYunFileConsumer.accept(weiYunFile);
        }
        Stack<WeiYunDirectory> weiYunDirectoryStack = new Stack<>();
        for(WeiYunDirectory weiYunDirectory:weiYunShareView.weiYunDirectoryList){
            weiYunDirectoryStack.push(weiYunDirectory);
        }
        while(!weiYunDirectoryStack.isEmpty()){
            WeiYunDirectory weiYunDirectory = weiYunDirectoryStack.pop();
            weiyunShareDirList(weiYunShareView,weiYunDirectory);
            for(WeiYunFile weiYunFile:weiYunDirectory.weiYunFileList){
                weiYunFile.parentWeiYunDirectory = weiYunDirectory;
                weiYunFileConsumer.accept(weiYunFile);
            }
            for(WeiYunDirectory subWeiYunDirectory:weiYunDirectory.weiYunDirectoryList){
                weiYunDirectoryStack.push(subWeiYunDirectory);
            }
        }
    }

    @Override
    public WeiYunFileDownload weiyunShareBatchDownload(WeiYunFile weiYunFile) throws IOException {
        String api = "https://share.weiyun.com/webapp/json/weiyunShare/WeiyunShareBatchDownload?refer=chrome_windows&g_tk=" + gtk + "&r=" + Math.random();
        String body = getBody(12024, "\\\".weiyun.WeiyunShareBatchDownloadMsgReq_body\\\":{\\\"share_key\\\":\\\""+weiYunFile.weiYunShareView.shareKey+"\\\",\\\"pwd\\\":\\\""+weiYunFile.weiYunShareView.sharePwd+"\\\",\\\"file_owner\\\":null,\\\"download_type\\\":0,\\\"file_list\\\":[{\\\"pdir_key\\\":\\\""+weiYunFile.pdirKey+"\\\",\\\"file_id\\\":\\\""+weiYunFile.fileId+"\\\",\\\"filename\\\":\\\""+weiYunFile.fileName+"\\\",\\\"file_size\\\":"+weiYunFile.fileSize+"}]}");
        Response response = QuickHttp.connect(api)
                .requestBody(body)
                .execute();
        JSONObject responseMessageBody = response.bodyAsJSONObject().getJSONObject("data").getJSONObject("rsp_body").getJSONObject("RspMsg_body");
        JSONObject result = responseMessageBody.getJSONArray("file_list").getJSONObject(0);
        WeiYunFileDownload weiYunFileDownload = getWeiYunFileDownload(result);
        return weiYunFileDownload;
    }

    @Override
    public WeiYunShareSave weiyunSharePartSaveData(WeiYunShareView weiYunShareView, WeiYunDirectory weiYunDirectory) throws IOException {
        String api = "https://share.weiyun.com/webapp/json/weiyunShare/WeiyunSharePartSaveData?refer=chrome_windows&g_tk=" + gtk + "&r=" + Math.random();
        StringBuilder bodyBuilder = new StringBuilder("\\\".weiyun.WeiyunSharePartSaveDataMsgReq_body\\\":{\\\"os_info\\\":\\\"windows\\\",\\\"browser\\\":\\\"chrome\\\",\\\"share_key\\\":\\\"" + weiYunShareView.shareKey + "\\\",\\\"pwd\\\":\\\"\\\",");
        bodyBuilder.append("\\\"dst_ppdir_key\\\":\\\"" + weiYunDirectory.pdirKey + "\\\",\\\"dst_pdir_key\\\":\\\"" + weiYunDirectory.dirKey + "\\\",\\\"src_pdir_key\\\":\\\"\\\",\\\"dir_list\\\":[],\\\"note_list\\\":[],");
        bodyBuilder.append("\\\"file_list\\\":[");
        for (WeiYunFile weiYunFile : weiYunShareView.weiYunFileList) {
            bodyBuilder.append("{\\\"pdir_key\\\":\\\"" + weiYunFile.pdirKey + "\\\",\\\"file_id\\\":\\\"" + weiYunFile.fileId + "\\\",\\\"filename\\\":\\\"" + weiYunFile.fileName + "\\\",\\\"file_size\\\":" + weiYunFile.fileSize + "},");
        }
        bodyBuilder.deleteCharAt(bodyBuilder.length() - 1);
        bodyBuilder.append("],\\\"is_save_all\\\":true}");
        String body = getBody(12025, bodyBuilder.toString());
        Response response = QuickHttp.connect(api)
                .requestBody(body)
                .execute();
        WeiYunShareSave weiYunShareSave = getResponse(response,WeiYunShareSave.class);
        return weiYunShareSave;
    }

    @Override
    public List<WeiYunShare> weiyunShareList() throws IOException {
        String api = "https://www.weiyun.com/webapp/json/weiyunShare/WeiyunShareList?refer=chrome_windows&g_tk=" + gtk + "&r=" + Math.random();
        String body = getBody(12008, "\\\".weiyun.WeiyunShareListMsgReq_body\\\":{\\\"offset\\\":0,\\\"size\\\":20,\\\"order\\\":0}");
        Response response = QuickHttp.connect(api)
                .requestBody(body)
                .execute();
        JSONObject responseMessageBody = response.bodyAsJSONObject().getJSONObject("data").getJSONObject("rsp_body").getJSONObject("RspMsg_body");
        JSONArray array = responseMessageBody.getJSONArray("item");
        List<WeiYunShare> weiYunShareList = array.toJavaList(WeiYunShare.class);
        return weiYunShareList;
    }

    @Override
    public WeiYunShare weiyunShareAddV2(List<WeiYunDirectory> weiYunDirectoryList, List<WeiYunFile> weiYunFileList) throws IOException {
        if (null == weiYunDirectoryList && null == weiYunFileList) {
            throw new IllegalArgumentException("文件夹列表和文件列表参数不能同时为空!");
        }
        String zipName = generateFileName(weiYunDirectoryList, weiYunFileList);
        if (null == weiYunDirectoryList) {
            weiYunDirectoryList = new ArrayList<>();
        }
        if (null == weiYunFileList) {
            weiYunFileList = new ArrayList<>();
        }
        String api = "https://www.weiyun.com/webapp/json/weiyunShare/WeiyunShareAddV2?refer=chrome_windows&g_tk=" + gtk + "&r=" + Math.random();
        StringBuilder bodyBuilder = new StringBuilder("\\\".weiyun.WeiyunShareAddV2MsgReq_body\\\":{\\\"note_list\\\":[],\\\"dir_list\\\":[");
        for (WeiYunDirectory weiYunDirectory : weiYunDirectoryList) {
            bodyBuilder.append("{\\\"pdir_key\\\":\\\"" + weiYunDirectory.pdirKey + "\\\",\\\"dir_key\\\":\\\"" + weiYunDirectory.dirKey + "\\\"},");
        }
        if (weiYunDirectoryList.size() > 0) {
            bodyBuilder.deleteCharAt(bodyBuilder.length() - 1);
        }
        bodyBuilder.append("],\\\"file_list\\\":[");
        for (WeiYunFile weiYunFile : weiYunFileList) {
            bodyBuilder.append("{\\\"pdir_key\\\":\\\"" + weiYunFile.pdirKey + "\\\",\\\"file_id\\\":\\\"" + weiYunFile.fileId + "\\\"},");
        }
        if (weiYunFileList.size() > 0) {
            bodyBuilder.deleteCharAt(bodyBuilder.length() - 1);
        }
        bodyBuilder.append("],\\\"share_type\\\":0,\\\"share_name\\\":\\\"" + zipName + "\\\"}");
        String body = getBody(12100, bodyBuilder.toString());
        Response response = QuickHttp.connect(api)
                .requestBody(body)
                .execute();
        WeiYunShare weiYunShare = getResponse(response,WeiYunShare.class);
        return weiYunShare;
    }

    @Override
    public void weiyunSharePwdCreate(WeiYunShare weiYunShare, String pwd) throws IOException {
        if (null == weiYunShare) {
            throw new IllegalArgumentException("分享文件不能为空!");
        }
        if (!pwd.matches("[A-Z|a-z|0-9]{6}")) {
            throw new IllegalArgumentException("密码必须为6位英文数字的组合!!");
        }
        String api = "https://www.weiyun.com/webapp/json/weiyunShare/WeiyunSharePwdCreate?refer=chrome_windows&g_tk=" + gtk + "&r=" + Math.random();
        String body = getBody(12012, "\\\".weiyun.WeiyunSharePwdCreateMsgReq_body\\\":{\\\"share_key\\\":\\\"" + weiYunShare.shareKey + "\\\",\\\"share_pwd\\\":\\\"" + pwd + "\\\"}");
        QuickHttp.connect(api)
                .requestBody(body)
                .execute();
    }

    @Override
    public void weiyunSharePwdModify(WeiYunShare weiYunShare, String pwd) throws IOException {
        if (null == weiYunShare) {
            throw new IllegalArgumentException("分享文件不能为空!");
        }
        if (!pwd.matches("[A-Z|a-z|0-9]{6}")) {
            throw new IllegalArgumentException("密码必须为6位英文数字的组合!!");
        }
        String api = "https://www.weiyun.com/webapp/json/weiyunShare/WeiyunSharePwdModify?refer=chrome_windows&g_tk=" + gtk + "&r=" + Math.random();
        String body = getBody(12013, "\\\".weiyun.WeiyunSharePwdModifyMsgReq_body\\\":{\\\"share_key\\\":\\\"" + weiYunShare.shareKey + "\\\",\\\"share_new_pwd\\\":\\\"" + pwd + "\\\"}");
        QuickHttp.connect(api)
                .requestBody(body)
                .execute();
    }

    @Override
    public List<WeiYunShareDelete> weiyunShareDelete(List<WeiYunShare> weiYunShareAddList) throws IOException {
        if (null == weiYunShareAddList) {
            throw new IllegalArgumentException("待删除分享列表不能为空!");
        }
        String api = "https://www.weiyun.com/webapp/json/weiyunShare/WeiyunShareDelete?refer=chrome_windows&g_tk=" + gtk + "&r=" + Math.random();
        StringBuilder bodyBuilder = new StringBuilder("\\\".weiyun.WeiyunShareDeleteMsgReq_body\\\":{\\\"share_key_list\\\":[");
        for (WeiYunShare weiYunShareAdd : weiYunShareAddList) {
            bodyBuilder.append("\\\"" + weiYunShareAdd.shareKey + "\\\",");
        }
        if (weiYunShareAddList.size() > 0) {
            bodyBuilder.deleteCharAt(bodyBuilder.length() - 1);
        }
        bodyBuilder.append("]}");
        String body = getBody(12007, bodyBuilder.toString());
        Response response = QuickHttp.connect(api)
                .requestBody(body)
                .execute();
        JSONObject responseMessageBody = response.bodyAsJSONObject().getJSONObject("data").getJSONObject("rsp_body").getJSONObject("RspMsg_body");
        JSONArray array = responseMessageBody.getJSONArray("ret_item_list");
        List<WeiYunShareDelete> weiYunShareDeleteList = array.toJavaList(WeiYunShareDelete.class);
        return weiYunShareDeleteList;
    }

    @Override
    public WeiYunDirectory fileSearchbyKeyWord(String keyword) throws IOException {
        String api = "https://www.weiyun.com/webapp/json/weiyunFileSearch/FileSearchbyKeyWord?refer=chrome_windows&g_tk=" + gtk + "&r=" + Math.random();
        String body = getBody(247251, "\\\".weiyun.FileSearchbyKeyWordMsgReq_body\\\":{\\\"type\\\":0,\\\"key_word\\\":\\\"" + keyword + "\\\",\\\"local_context\\\":\\\"\\\",\\\"location\\\":0}");
        Response response = QuickHttp.connect(api)
                .requestBody(body)
                .execute();
        JSONObject responseMessageBody = response.bodyAsJSONObject().getJSONObject("data").getJSONObject("rsp_body").getJSONObject("RspMsg_body");
        JSONArray array = responseMessageBody.getJSONArray("search_result_list");
        WeiYunDirectory weiYunDirectory = new WeiYunDirectory();
        for (int i = 0; i < array.size(); i++) {
            JSONObject o = array.getJSONObject(i);
            if (o.containsKey("type") && o.getInteger("type") == 2) {
                JSONObject dirItem = o.getJSONObject("dir_item");
                WeiYunDirectory subWeiYunDirectory = dirItem.toJavaObject(WeiYunDirectory.class);
                weiYunDirectory.weiYunDirectoryList.add(subWeiYunDirectory);
            } else if (o.containsKey("type") && o.getInteger("type") == 1) {
                JSONObject fileItem = o.getJSONObject("file_item");
                WeiYunFile subWeiYunFile = fileItem.toJavaObject(WeiYunFile.class);
                subWeiYunFile.fileCreatedTime = fileItem.getDate("file_ctime");
                weiYunDirectory.weiYunFileList.add(subWeiYunFile);
            }
        }
        return weiYunDirectory;
    }

    @Override
    public WeiYunDirectory diskRecycleList() throws IOException {
        String api = "https://www.weiyun.com/webapp/json/weiyunQdiskClient/DiskRecycleList?refer=chrome_windows&g_tk=" + gtk + "&r=" + Math.random();
        String body = getBody(2702, "\\\".weiyun.DiskRecycleListMsgReq_body\\\":{\\\"start\\\":0,\\\"count\\\":100,\\\"sort_field\\\":2,\\\"reverse_order\\\":false,\\\"get_abstract_url\\\":true}");
        Response response = QuickHttp.connect(api)
                .requestBody(body)
                .execute();
        JSONObject responseMessageBody = response.bodyAsJSONObject().getJSONObject("data").getJSONObject("rsp_body").getJSONObject("RspMsg_body");
        WeiYunDirectory weiYunDirectory = new WeiYunDirectory();
        weiYunDirectory.weiYunFileList = getWeiYunFileList(responseMessageBody.getJSONArray("file_list"), null, null);
        weiYunDirectory.weiYunDirectoryList = getWeiYunDirectoryList(responseMessageBody.getJSONArray("dir_list"), null, null);
        return weiYunDirectory;
    }

    @Override
    public WeiYunDirectoryDelete diskRecycleDirFileBatchRestore(List<WeiYunDirectory> weiYunDirectoryList, List<WeiYunFile> weiYunFileList) throws IOException {
        if (null == weiYunDirectoryList) {
            weiYunDirectoryList = new ArrayList<>();
        }
        if (null == weiYunFileList) {
            weiYunFileList = new ArrayList<>();
        }
        String api = "https://www.weiyun.com/webapp/json/weiyunQdiskClient/DiskRecycleDirFileBatchRestore?refer=chrome_windows&g_tk=" + gtk + "&r=" + Math.random();
        StringBuilder bodyBuilder = new StringBuilder("\\\".weiyun.DiskRecycleDirFileBatchRestoreMsgReq_body\\\":{\\\"file_list\\\":[");
        for (WeiYunFile weiYunFile : weiYunFileList) {
            bodyBuilder.append("{\\\"recycle_file_id\\\":\\\"" + weiYunFile.fileId + "\\\",\\\"recycle_filename\\\":\\\"" + weiYunFile.fileName + "\\\"},");
        }
        if (weiYunFileList.size() > 0) {
            bodyBuilder.deleteCharAt(bodyBuilder.length() - 1);
        }
        bodyBuilder.append("],\\\"dir_list\\\":[");
        for (WeiYunDirectory weiYunDirectory : weiYunDirectoryList) {
            bodyBuilder.append("{\\\"recycle_dir_key\\\":\\\"" + weiYunDirectory.dirKey + "\\\",\\\"recycle_dir_name\\\":\\\"" + weiYunDirectory.dirName + "\\\"},");
        }
        if (weiYunDirectoryList.size() > 0) {
            bodyBuilder.deleteCharAt(bodyBuilder.length() - 1);
        }
        bodyBuilder.append("]}");
        String body = getBody(2708, bodyBuilder.toString());
        Response response = QuickHttp.connect(api)
                .requestBody(body)
                .execute();
        JSONObject responseMessageBody = response.bodyAsJSONObject().getJSONObject("data").getJSONObject("rsp_body").getJSONObject("RspMsg_body");
        WeiYunDirectoryDelete weiYunDirectoryDelete = new WeiYunDirectoryDelete();
        if (responseMessageBody.containsKey("dir_list")) {
            weiYunDirectoryDelete.weiYunDirectoryDeleteList.addAll(responseMessageBody.getJSONArray("dir_list").toJavaList(WeiYunDirectoryDelete.class));
        }
        if (responseMessageBody.containsKey("file_list")) {
            weiYunDirectoryDelete.weiYunFileDeleteList.addAll(responseMessageBody.getJSONArray("file_list").toJavaList(WeiYunFileDelete.class));
        }
        return weiYunDirectoryDelete;
    }

    @Override
    public void diskRecycleClear() throws IOException {
        String api = "https://www.weiyun.com/webapp/json/weiyunQdiskClient/DiskRecycleClear?refer=chrome_windows&g_tk=" + gtk + "&r=" + Math.random();
        String body = getBody(2703, "\\\".weiyun.DiskRecycleClearMsgReq_body\\\":{}");
        QuickHttp.connect(api)
                .requestBody(body)
                .execute();
    }

    @Override
    public WeiYunDirectoryDelete diskRecycleDirFileClear(List<WeiYunDirectory> weiYunDirectoryList, List<WeiYunFile> weiYunFileList) throws IOException {
        if (null == weiYunDirectoryList) {
            weiYunDirectoryList = new ArrayList<>();
        }
        if (null == weiYunFileList) {
            weiYunFileList = new ArrayList<>();
        }
        String api = "https://www.weiyun.com/webapp/json/weiyunQdiskClient/DiskRecycleDirFileClear?refer=chrome_windows&g_tk=" + gtk + "&r=" + Math.random();
        StringBuilder bodyBuilder = new StringBuilder("\\\".weiyun.DiskRecycleDirFileClearMsgReq_body\\\":{\\\"file_list\\\":[");
        for (WeiYunFile weiYunFile : weiYunFileList) {
            bodyBuilder.append("{\\\"file_id\\\":\\\"" + weiYunFile.fileId + "\\\",\\\"filename\\\":\\\"" + weiYunFile.fileName + "\\\"},");
        }
        if (weiYunFileList.size() > 0) {
            bodyBuilder.deleteCharAt(bodyBuilder.length() - 1);
        }
        bodyBuilder.append("],\\\"dir_list\\\":[");
        for (WeiYunDirectory weiYunDirectory : weiYunDirectoryList) {
            bodyBuilder.append("{\\\"dir_key\\\":\\\"" + weiYunDirectory.dirKey + "\\\",\\\"dir_name\\\":\\\"" + weiYunDirectory.dirName + "\\\"},");
        }
        if (weiYunDirectoryList.size() > 0) {
            bodyBuilder.deleteCharAt(bodyBuilder.length() - 1);
        }
        bodyBuilder.append("]}");
        String body = getBody(2710, bodyBuilder.toString());
        Response response = QuickHttp.connect(api)
                .requestBody(body)
                .execute();
        JSONObject responseMessageBody = response.bodyAsJSONObject().getJSONObject("data").getJSONObject("rsp_body").getJSONObject("RspMsg_body");
        WeiYunDirectoryDelete weiYunDirectoryDelete = new WeiYunDirectoryDelete();
        if (responseMessageBody.containsKey("dir_list")) {
            weiYunDirectoryDelete.weiYunDirectoryDeleteList.addAll(responseMessageBody.getJSONArray("dir_list").toJavaList(WeiYunDirectoryDelete.class));
        }
        if (responseMessageBody.containsKey("file_list")) {
            weiYunDirectoryDelete.weiYunFileDeleteList.addAll(responseMessageBody.getJSONArray("file_list").toJavaList(WeiYunFileDelete.class));
        }
        return weiYunDirectoryDelete;
    }

    private WeiYunShareView getWeiYunShareView(String url, boolean login) throws IOException {
        String sharePwd = null;
        if(url.contains("#")){
            sharePwd = "\\\""+url.substring(url.indexOf("#")+1)+"\\\"";
            url = url.substring(0,url.indexOf("#"));
        }
        String shareKey = url.substring(url.lastIndexOf("/") + 1);
        String api = "https://share.weiyun.com/webapp/json/weiyunShare" + (login ? "" : "NoLogin") + "/WeiyunShareView?refer=chrome_windows&g_tk=" + (gtk == null ? "854045919" : gtk) + "&r=" + Math.random();
        String body = getBody(12002, "\\\".weiyun.WeiyunShareViewMsgReq_body\\\":{\\\"share_pwd\\\":" + sharePwd + ",\\\"share_key\\\":\\\"" + shareKey + "\\\"}");
        Response response = QuickHttp.connect(api)
                .requestBody(body)
                .execute();
        JSONObject responseMessageBody = response.bodyAsJSONObject().getJSONObject("data").getJSONObject("rsp_body").getJSONObject("RspMsg_body");
        WeiYunShareView weiYunShareView = responseMessageBody.toJavaObject(WeiYunShareView.class);
        weiYunShareView.sharePwd = sharePwd;
        weiYunShareView.fileCreatedTime = responseMessageBody.getDate("create_time");
        weiYunShareView.weiYunFileList = getWeiYunFileList(responseMessageBody.getJSONArray("file_list"), weiYunShareView.pdirKey, null);
        weiYunShareView.weiYunDirectoryList = getWeiYunDirectoryList(responseMessageBody.getJSONArray("dir_list"), weiYunShareView.pdirKey, null);
        for(WeiYunFile weiYunFile:weiYunShareView.weiYunFileList){
            weiYunFile.weiYunShareView = weiYunShareView;
        }
        return weiYunShareView;
    }

    private WeiYunDirectory diskDirBatchList(String pdirKey, String dirKey) throws IOException {
        String api = "https://www.weiyun.com/webapp/json/weiyunQdisk/DiskDirBatchList?refer=chrome_windows&g_tk=" + gtk + "&r=" + Math.random();
        String body = getBody(2209, "\\\".weiyun.DiskDirBatchListMsgReq_body\\\":{\\\"pdir_key\\\":\\\"" + pdirKey + "\\\",\\\"dir_list\\\":[{\\\"dir_key\\\":\\\"" + dirKey + "\\\",\\\"get_type\\\":0,\\\"start\\\":0,\\\"count\\\":100,\\\"sort_field\\\":2,\\\"reverse_order\\\":false,\\\"get_abstract_url\\\":true,\\\"get_dir_detail_info\\\":true}]}");
        Response response = QuickHttp.connect(api)
                .method(Request.Method.POST)
                .requestBody(body)
                .execute();
        JSONObject result = response.bodyAsJSONObject().getJSONObject("data").getJSONObject("rsp_body").getJSONObject("RspMsg_body").getJSONArray("dir_list").getJSONObject(0);
        WeiYunDirectory weiYunDirectory = new WeiYunDirectory();
        weiYunDirectory.pdirKey = result.getString("pdir_key");
        weiYunDirectory.weiYunFileList = getWeiYunFileList(result.getJSONArray("file_list"), dirKey, pdirKey);
        weiYunDirectory.weiYunDirectoryList = getWeiYunDirectoryList(result.getJSONArray("dir_list"), dirKey, pdirKey);
        return weiYunDirectory;
    }

    private List<WeiYunDirectory> getWeiYunDirectoryList(JSONArray directoryList, String pdirKey, String ppdirKey) {
        List<WeiYunDirectory> weiYunDirectoryList = directoryList.toJavaList(WeiYunDirectory.class);
        for(WeiYunDirectory weiYunDirectory:weiYunDirectoryList){
            if (null == weiYunDirectory.pdirKey) {
                weiYunDirectory.pdirKey = pdirKey;
            }
            if (null == weiYunDirectory.ppdirKey) {
                weiYunDirectory.ppdirKey = ppdirKey;
            }
        }
        return weiYunDirectoryList;
    }

    private List<WeiYunFile> getWeiYunFileList(JSONArray fileList, String pdirKey, String ppdirKey) {
        List<WeiYunFile> weiYunFileList = new ArrayList<>();
        for (int i = 0; i < fileList.size(); i++) {
            JSONObject o = fileList.getJSONObject(i);

            WeiYunFile weiYunFile = new WeiYunFile();
            weiYunFile.fileId = o.getString("file_id");
            weiYunFile.fileName = o.getString("filename");
            if (null == weiYunFile.fileName) {
                weiYunFile.fileName = o.getString("file_name");
            }
            if (null != weiYunFile.fileName) {
                if (weiYunFile.fileName.lastIndexOf(".") > 0) {
                    weiYunFile.fileNameSuffix = weiYunFile.fileName.substring(weiYunFile.fileName.lastIndexOf(".") + 1);
                }
            }
            if (o.containsKey("file_size")) {
                weiYunFile.fileSize = o.getLong("file_size");
            }
            weiYunFile.fileCreatedTime = o.getDate("file_ctime");
            if (null == weiYunFile.fileCreatedTime) {
                weiYunFile.fileCreatedTime = o.getDate("file_mtime");
            }
            weiYunFile.pdirKey = o.getString("pdir_key");
            if (null == weiYunFile.pdirKey) {
                weiYunFile.pdirKey = pdirKey;
            }
            weiYunFile.ppdirKey = o.getString("ppdir_key");
            if (null == weiYunFile.ppdirKey) {
                weiYunFile.ppdirKey = ppdirKey;
            }
            weiYunFileList.add(weiYunFile);
        }
        return weiYunFileList;
    }

    /**获取微云下载信息*/
    private WeiYunFileDownload getWeiYunFileDownload(JSONObject result) {
        WeiYunFileDownload weiYunFileDownload = result.toJavaObject(WeiYunFileDownload.class);
        weiYunFileDownload.fileModifiedTime = result.getDate("file_mtime");
        weiYunFileDownload.insideDownloadIP = result.getString("inside_download_ip");
        weiYunFileDownload.outsideDownloadIP = result.getString("outside_download_ip");
        weiYunFileDownload.dlink = QuickHttp.newQuickHttpClient()
                .connect(weiYunFileDownload.httpsDownloadUrl)
                .cookie(weiYunFileDownload.cookieName, weiYunFileDownload.cookieValue)
                .connectTimeout(10000);
        return weiYunFileDownload;
    }

    /**
     * 获取请求体
     */
    private String getBody(int cmd, String condition) {
        return "{\"req_header\":\"{\\\"seq\\\":15677596144092318,\\\"type\\\":1,\\\"cmd\\\":" + cmd + ",\\\"appid\\\":30013,\\\"version\\\":3,\\\"major_version\\\":3,\\\"minor_version\\\":3,\\\"fix_version\\\":3,\\\"wx_openid\\\":\\\"\\\",\\\"user_flag\\\":0}\",\"req_body\":\"{\\\"ReqMsg_body\\\":{\\\"ext_req_head\\\":{\\\"token_info\\\":{\\\"token_type\\\":0,\\\"login_key_type\\\":1,\\\"login_key_value\\\":\\\"" + (skey == null ? "" : skey) + "\\\"},\\\"language_info\\\":{\\\"language_type\\\":2052}}," + condition + "}}\"}";
    }

    /**
     * 获取返回体
     * */
    private <T> T getResponse(Response response, Class<T> returnType) throws IOException {
        JSONObject result = response.bodyAsJSONObject().getJSONObject("data").getJSONObject("rsp_body").getJSONObject("RspMsg_body");
        return result.toJavaObject(returnType);
    }

    /**
     * 生成文件名
     */
    private String generateFileName(List<WeiYunDirectory> weiYunDirectoryList, List<WeiYunFile> weiYunFileList) throws UnsupportedEncodingException {
        String zipName = null;
        if (null == weiYunDirectoryList) {
            String firstFileName = weiYunFileList.get(0).fileName;
            zipName = weiYunFileList.size() == 1 ? firstFileName : firstFileName + URLEncoder.encode("等" + weiYunFileList.size() + "个文件", "utf-8");
        }
        if (null == weiYunFileList) {
            String firstDirName = weiYunDirectoryList.get(0).dirName;
            zipName = weiYunDirectoryList.size() == 1 ? firstDirName : firstDirName + URLEncoder.encode("等" + weiYunDirectoryList.size() + "个文件", "utf-8");
        }
        if (null == zipName) {
            zipName = weiYunFileList.get(0).fileName + URLEncoder.encode("等" + (weiYunDirectoryList.size() + weiYunFileList.size()) + "个文件", "utf-8");
        }
        return zipName;
    }
}